#include <qpe/config.h>
#include <qmap.h>

#include "KeyBindManager.h"
#include "keycodeutil.h"

typedef struct bind_pair
{
	int qt;
	KeyBindManager::Key host;
	bind_pair(int qc, const KeyBindManager::Key &hc): qt(qc), host(hc)	{}
} BindPair;

static BindPair DefaultBinds[] = {
		BindPair('0', KeyBindManager::Key('0')),
		BindPair('1', KeyBindManager::Key('1')),
		BindPair('2', KeyBindManager::Key('2')),
		BindPair('3', KeyBindManager::Key('3')),
		BindPair('4', KeyBindManager::Key('4')),
		BindPair('5', KeyBindManager::Key('5')),
		BindPair('6', KeyBindManager::Key('6')),
		BindPair('7', KeyBindManager::Key('7')),
		BindPair('8', KeyBindManager::Key('8')),
		BindPair('9', KeyBindManager::Key('9')),
		BindPair('A', KeyBindManager::Key('A')),
		BindPair('B', KeyBindManager::Key('B')),
		BindPair('C', KeyBindManager::Key('C')),
		BindPair('D', KeyBindManager::Key('D')),
		BindPair('E', KeyBindManager::Key('E')),
		BindPair('F', KeyBindManager::Key('F')),
		BindPair('G', KeyBindManager::Key('G')),
		BindPair('H', KeyBindManager::Key('H')),
		BindPair('I', KeyBindManager::Key('I')),
		BindPair('J', KeyBindManager::Key('J')),
		BindPair('K', KeyBindManager::Key('K')),
		BindPair('L', KeyBindManager::Key('L')),
		BindPair('M', KeyBindManager::Key('M')),
		BindPair('N', KeyBindManager::Key('N')),
		BindPair('O', KeyBindManager::Key('O')),
		BindPair('P', KeyBindManager::Key('P')),
		BindPair('Q', KeyBindManager::Key('Q')),
		BindPair('R', KeyBindManager::Key('R')),
		BindPair('S', KeyBindManager::Key('S')),
		BindPair('T', KeyBindManager::Key('T')),
		BindPair('U', KeyBindManager::Key('U')),
		BindPair('V', KeyBindManager::Key('V')),
		BindPair('W', KeyBindManager::Key('W')),
		BindPair('X', KeyBindManager::Key('X')),
		BindPair('Y', KeyBindManager::Key('Y')),
		BindPair('Z', KeyBindManager::Key('Z')),
		BindPair(Qt::Key_Return, KeyBindManager::Key(HostKeyCodeByName("VK_RETURN"))),
		BindPair(Qt::Key_Shift, KeyBindManager::Key(HostKeyCodeByName("VK_SHIFT"))),
		BindPair(Qt::Key_BackSpace, KeyBindManager::Key(HostKeyCodeByName("VK_BACK"))),
		BindPair(Qt::Key_Space, KeyBindManager::Key(HostKeyCodeByName("VK_SPACE"))),
		BindPair(Qt::Key_Up, KeyBindManager::Key(HostKeyCodeByName("VK_UP"))),
		BindPair(Qt::Key_Down, KeyBindManager::Key(HostKeyCodeByName("VK_DOWN"))),
		BindPair(Qt::Key_Left, KeyBindManager::Key(HostKeyCodeByName("VK_LEFT"))),
		BindPair(Qt::Key_Right, KeyBindManager::Key(HostKeyCodeByName("VK_RIGHT"))),
		BindPair(Qt::Key_Escape, KeyBindManager::Key(HostKeyCodeByName("VK_ESCAPE"))),
		BindPair(Qt::Key_Comma, KeyBindManager::Key(HostKeyCodeByName("VK_OEM_COMMA"))),
		BindPair(Qt::Key_Period, KeyBindManager::Key(HostKeyCodeByName("VK_OEM_PERIOD"))),
		BindPair(Qt::Key_At, KeyBindManager::Key(HostKeyCodeByName("VK_OEM_3"))),
		BindPair(QtKeyCodeByName("Fn + N"), KeyBindManager::Key(HostKeyCodeByName("VK_OEM_2"))),
		BindPair(QtKeyCodeByName("Fn + M"), KeyBindManager::Key(HostKeyCodeByName("VK_OEM_2"), true)),
		BindPair(Qt::Key_Less, KeyBindManager::Key(HostKeyCodeByName("VK_OEM_COMMA"), true)),
		BindPair(Qt::Key_Greater, KeyBindManager::Key(HostKeyCodeByName("VK_OEM_PERIOD"), true)),
		BindPair(Qt::Key_AsciiCircum, KeyBindManager::Key(HostKeyCodeByName("VK_OEM_7"))),
		BindPair(Qt::Key_BracketLeft, KeyBindManager::Key(HostKeyCodeByName("VK_OEM_4"))),
		BindPair(Qt::Key_BracketRight, KeyBindManager::Key(HostKeyCodeByName("VK_OEM_6"))),
		BindPair(QtKeyCodeByName("Fn + K"), KeyBindManager::Key(HostKeyCodeByName("VK_OEM_5"))),
		BindPair(Qt::Key_Backslash, KeyBindManager::Key(HostKeyCodeByName("VK_OEM_102"))),
		BindPair(Qt::Key_Minus, KeyBindManager::Key(HostKeyCodeByName("VK_OEM_MINUS"))),
		BindPair(Qt::Key_Plus, KeyBindManager::Key(HostKeyCodeByName("VK_OEM_PLUS"), true)),
		BindPair(Qt::Key_Equal, KeyBindManager::Key(HostKeyCodeByName("VK_OEM_PLUS"))),
		BindPair(Qt::Key_Underscore, KeyBindManager::Key(HostKeyCodeByName("VK_OEM_MINUS"), true)),
		BindPair(Qt::Key_Colon, KeyBindManager::Key(HostKeyCodeByName("VK_OEM_1"), true)),
		BindPair(Qt::Key_Semicolon, KeyBindManager::Key(HostKeyCodeByName("VK_OEM_1"))),
		BindPair(Qt::Key_F12, KeyBindManager::Key(HostKeyCodeByName("VK_LWIN"))),	// Home
		BindPair(Qt::Key_Tab, KeyBindManager::Key(HostKeyCodeByName("VK_TAB"))),
		BindPair(Qt::Key_F11, KeyBindManager::Key(HostKeyCodeByName("VK_APPS"))),	// Menu
		BindPair(Qt::Key_Delete, KeyBindManager::Key(HostKeyCodeByName("VK_DELETE"))),
		BindPair(Qt::Key_F26, KeyBindManager::Key(HostKeyCodeByName("VK_CONTROL"))),	// Kana/Hira
		BindPair(Qt::Key_F21, KeyBindManager::Key(HostKeyCodeByName("VK_MENU"))),	// Zen/Han
		BindPair(Qt::Key_F33, KeyBindManager::Key(HostKeyCodeByName("VK_RETURN"))),	// OK
		BindPair(0x200f, KeyBindManager::Key(HostKeyCodeByName("VK_F1"))),
		BindPair(0x2010, KeyBindManager::Key(HostKeyCodeByName("VK_F2"))),
		BindPair(0x2012, KeyBindManager::Key(HostKeyCodeByName("VK_F3"))),
		BindPair(0x2011, KeyBindManager::Key(HostKeyCodeByName("VK_F4"))),
		BindPair(0x201b, KeyBindManager::Key(HostKeyCodeByName("VK_F5"))),
		BindPair(0x200a, KeyBindManager::Key(HostKeyCodeByName("VK_F6"))),
		BindPair(0x200b, KeyBindManager::Key(HostKeyCodeByName("VK_F7"))),
		BindPair(0x200c, KeyBindManager::Key(HostKeyCodeByName("VK_F8"))),
		BindPair(0x2007, KeyBindManager::Key(HostKeyCodeByName("VK_F9"))),
		BindPair(0x2008, KeyBindManager::Key(HostKeyCodeByName("VK_F10"))),
		BindPair(0x2015, KeyBindManager::Key(HostKeyCodeByName("VK_F11"))),
		BindPair(0x2016, KeyBindManager::Key(HostKeyCodeByName("VK_F12"))),
		BindPair(Qt::Key_Prior, KeyBindManager::Key(HostKeyCodeByName("VK_PRIOR"))),
		BindPair(Qt::Key_Next, KeyBindManager::Key(HostKeyCodeByName("VK_NEXT"))),
		BindPair(Qt::Key_Home, KeyBindManager::Key(HostKeyCodeByName("VK_HOME"))),
		BindPair(Qt::Key_End, KeyBindManager::Key(HostKeyCodeByName("VK_END"))),
/*
		BindPair(Qt::Key_, KeyBindManager::Key(HostKeyCodeByName("VK_"))),
		BindPair(, KeyBindManager::Key(HostKeyCodeByName(""))),
		BindPair(, KeyBindManager::Key()),
*/
		BindPair(Qt::Key_unknown, KeyBindManager::Key(0x00)),
	};

KeyBindManager::KeyBindManager(Config *conf): config(conf)
{
	config->setGroup("KeyBind");
	const int count = config->readNumEntry("count", 0);
	for (int i = 0; i != count; ++i)
	{
		QString bind = config->readEntry(QString().sprintf("%04d", i), "");
		if (bind.isEmpty())	continue;
		
		QString qtKey = bind.left(bind.find(':'));
		QString hostKey = bind.right(bind.length() - bind.find(':') - 1);
		
		bool shift = config->readBoolEntry(QString().sprintf("s%04d", i), false);
		
		appendBind(QtKeyCodeByName(qtKey), KeyBindManager::Key(HostKeyCodeByName(hostKey), shift));
	}
	
	if (count == 0)
		setDefaultBind();
}

KeyBindManager::~KeyBindManager()
{
	int count = binds.count();
	config->setGroup("KeyBind");
	config->writeEntry("count", count);
	for ({BindMap::ConstIterator it = binds.begin(); int i = 0;} it != binds.end(); ++it, ++i)
	{
		config->writeEntry(QString().sprintf("%04d", i), QString("%1:%2").arg(QtKeyNameByCode(it.key())).arg(HostKeyNameByCode(it.data().code)));
		config->writeEntry(QString().sprintf("s%04d", i), it.data().shift);
	}
}

void KeyBindManager::setDefaultBind()
{
	binds.clear();
	for (int i = 0; DefaultBinds[i].qt != Qt::Key_unknown; ++i)
		appendBind(DefaultBinds[i].qt, DefaultBinds[i].host);
}

const KeyBindManager::Key & KeyBindManager::hostKeyCodeByQtKeyCode(int c) const
{
	return binds[c];
}

void KeyBindManager::clear()
{
	binds.clear();
}

bool KeyBindManager::appendBind(int qt, const Key &host)
{
	if (binds.contains(qt))
		return false;
	
	binds.insert(qt, host);
	
	return true;
}

const KeyBindManager::BindMap & KeyBindManager::bindMap() const
{
	return binds;
}
